﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Web.Configuration;
using System.Web.UI;
using ErrorPageZ.Classes;
using ErrorPageZ.Providers;
using visinia.SmartEngine;
using visinia.SmartEngine.Cache;
using visinia.SmartEngine.Pages;
using visinia.SmartEngine.Installer;

namespace ErrorPageZ.Controllers
{
    public class CustomErrorPagesController
    {
        #region Error Pages
        private static List<CustomErrorPageInfo> GetCustomErrorPages()
        {
            List<CustomErrorPageInfo> list = (List<CustomErrorPageInfo>)DataCache.GetCache("CustomErrorPageInfos");
            if (list == null)
            {
                IDataReader dr = ErrorPageZDataProvider.Provider.GetCustomErrorPages();
                list = new List<CustomErrorPageInfo>();
                while (dr.Read())
                {
                    CustomErrorPageInfo info = new CustomErrorPageInfo();
                    if (dr["statusCode"] != Convert.DBNull)
                        info.statusCode = (int)dr["statusCode"];
                    if (dr["redirect"] != Convert.DBNull)
                        info.redirect = (string)dr["redirect"];
                    if (dr["PageId"] != Convert.DBNull)
                        info.PageId = (int)dr["PageId"];
                    list.Add(info);
                }
                dr.Close();
                DataCache.SetCache("CustomErrorPageInfos", list);
            }
            return list;
        }

        public static CustomErrorPageInfo GetCustomErrorPage(int statusCode)
        {
            return GetCustomErrorPages().Find(p=> p.statusCode == statusCode);            
        }

        public static void SetCustomErrorPage(int statusCode, Page Page)
        {
            StatusCodeInfo statusCodeInfo = StatusCodesController.StatusCodes().Find(p=>p.statusCode == statusCode);
            if(statusCodeInfo != null)
            {
                if (statusCodeInfo.Set)
                {// Custom Error Page already Exists

                }
                else
                {
                    //Create Custom Error Page
                    int visiniaPageId = PageController.AddPage(new PageInfo(statusCodeInfo.statusCode.ToString(), statusCodeInfo.Name, PluginController.GetInstalledPlugin("ErrorPageZ").PluginId));
                    string redirect = "Default.aspx?PageId=" + visiniaPageId;
                    //backup web.config
                    BackupConfigurationFile(Page);
                    //update web.config
                    UpdateErrorPageConfiguration(statusCode, redirect, Page);
                    ErrorPageZDataProvider.Provider.SetCustomErrorPage(statusCodeInfo.statusCode, redirect, visiniaPageId);
                    DataCache.DeleteCacheMultiple("CustomErrorPageInfos");
                }
            }
        }

        public static void ResetCustomErrorPage(int statusCode, Page Page)
        {
            StatusCodeInfo statusCodeInfo = StatusCodesController.StatusCodes().Find(p => p.statusCode == statusCode);
            if (statusCodeInfo != null)
            {
                if (statusCodeInfo.Set)
                {
                    // remove visinia page
                    PageController.DeletePage(statusCodeInfo.PageId);
                    //backup web.config
                    BackupConfigurationFile(Page);
                    //update web.config                    
                    RemoveErrorPageConfiguration(statusCode, Page);
                    // delete the association
                    ErrorPageZDataProvider.Provider.ResetCustomErrorPage(statusCode);
                    DataCache.DeleteCacheMultiple("CustomErrorPageInfos");
                }
                else
                {
                    // Custom Error Page Doesn't Exists
                }
            }            
        }
        
        private static void UpdateErrorPageConfiguration(int statusCode, string redirect, Page Page)
        {
            WebConfigurationFileMap fileMap = new CustomErrorPagesController().CreateFileMap(Page);
            System.Configuration.Configuration config = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, "/");
            CustomErrorsSection customErrorsSection = (CustomErrorsSection)config.GetSection("system.web/customErrors");
            CustomErrorCollection customErrorsCollection = customErrorsSection.Errors;
            CustomError newCustomError = new CustomError(statusCode, redirect);
            if (!customErrorsSection.SectionInformation.IsLocked)
            {
                customErrorsCollection.Set(newCustomError);
                config.Save();
            }
        }

        private static void RemoveErrorPageConfiguration(int statusCode, Page Page)
        {
            WebConfigurationFileMap fileMap = new CustomErrorPagesController().CreateFileMap(Page);
            System.Configuration.Configuration config = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, "/");
            CustomErrorsSection customErrorsSection = (CustomErrorsSection)config.GetSection("system.web/customErrors");
            CustomErrorCollection customErrorsCollection = customErrorsSection.Errors;            
            if (!customErrorsSection.SectionInformation.IsLocked)
            {
                customErrorsCollection.Remove(statusCode.ToString());
                config.Save();
            }
        }
        #endregion

        #region Utility
        public WebConfigurationFileMap CreateFileMap(Page Page)
        {
            WebConfigurationFileMap fileMap = new WebConfigurationFileMap();
            // Get he physical directory where this app runs.
            // We'll use it to map the virtual directories
            // defined next.                 
            string physDir = Page.Server.MapPath(WebRoots.GetRelativeWebRoot);
            // Create a VirtualDirectoryMapping object to use
            // as the root directory for the virtual directory        
            // Note: you must assure that you have a physical subdirectory
            // named config in the curremt physical directory where this
            // application runs.
            VirtualDirectoryMapping vDirMap = new VirtualDirectoryMapping(physDir, true);
            // Add vDirMap to the VirtualDirectories collection 
            // assigning to it the virtual directory name.
            //     fileMap.VirtualDirectories.Add("/config", vDirMap);
            // Create a VirtualDirectoryMapping object to use
            // as the default directory for all the virtual 
            // directories.
            VirtualDirectoryMapping vDirMapBase = new VirtualDirectoryMapping(physDir, true, "web.config");
            // Add it to the virtual directory mapping collection.
            fileMap.VirtualDirectories.Add("/", vDirMapBase);
            // Return the mapping.
            return fileMap;
        } 

        private static void BackupConfigurationFile(Page Page)
        {
            WebConfigurationFileMap fileMap = new CustomErrorPagesController().CreateFileMap(Page);
            System.Configuration.Configuration config = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, "/");
            config.SaveAs(Page.Server.MapPath(WebRoots.GetRelativeWebRoot + "oldweb.config"));            
        }
        #endregion

        #region MODES
        public static CustomErrorsMode GetCustomErrorsMode(Page Page)
        {
            WebConfigurationFileMap fileMap = new CustomErrorPagesController().CreateFileMap(Page);
            System.Configuration.Configuration config = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, "/");
            CustomErrorsSection customErrorsSection = (CustomErrorsSection)config.GetSection("system.web/customErrors");
            return customErrorsSection.Mode;            
        }

        public static void SetCustomErrorsMode(CustomErrorsMode Mode, Page Page)
        {
            //backup web.config
            BackupConfigurationFile(Page);

            WebConfigurationFileMap fileMap = new CustomErrorPagesController().CreateFileMap(Page);
            System.Configuration.Configuration config = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, "/");
            CustomErrorsSection customErrorsSection = (CustomErrorsSection)config.GetSection("system.web/customErrors");
            customErrorsSection.Mode = Mode;
            if (!customErrorsSection.SectionInformation.IsLocked)
                config.Save();            
        }
        #endregion

        #region Default Redirect
        public static CustomErrorPageInfo GetDefaultRedirect(Page Page)
        {
            return GetCustomErrorPage(0);            
        }

        public static void SetDefaultRedirect(Page Page)
        {
            //Create Default Redirect Page
            int visiniaPageId = PageController.AddPage(new PageInfo("Default Redirect", "Default Redirect", PluginController.GetInstalledPlugin("ErrorPageZ").PluginId));
            string redirect = "Default.aspx?PageId=" + visiniaPageId;
            ErrorPageZDataProvider.Provider.SetCustomErrorPage(0, redirect, visiniaPageId);
            DataCache.DeleteCacheMultiple("CustomErrorPageInfos");

            //backup web.config
            BackupConfigurationFile(Page);

            WebConfigurationFileMap fileMap = new CustomErrorPagesController().CreateFileMap(Page);
            System.Configuration.Configuration config = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, "/");
            CustomErrorsSection customErrorsSection = (CustomErrorsSection)config.GetSection("system.web/customErrors");
            customErrorsSection.DefaultRedirect  = redirect;
            if (!customErrorsSection.SectionInformation.IsLocked)
                config.Save();
        }

        public static void ResetDefaultRedirect(Page Page)
        {
            CustomErrorPageInfo info = GetCustomErrorPage(0);
            if (info == null)
                return;
            // remove visinia page
            PageController.DeletePage(info.PageId);
            // delete the association
            ErrorPageZDataProvider.Provider.ResetCustomErrorPage(0);
            DataCache.DeleteCacheMultiple("CustomErrorPageInfos");
            
            //backup web.config
            BackupConfigurationFile(Page);

            WebConfigurationFileMap fileMap = new CustomErrorPagesController().CreateFileMap(Page);
            System.Configuration.Configuration config = WebConfigurationManager.OpenMappedWebConfiguration(fileMap, "/");
            CustomErrorsSection customErrorsSection = (CustomErrorsSection)config.GetSection("system.web/customErrors");
            customErrorsSection.DefaultRedirect = "";
            if (!customErrorsSection.SectionInformation.IsLocked)                            
                config.Save();            
        }        
        #endregion
    }
}
